//
// Created by nilyang on 2021/11/26.
//

#include "String.h"

#include <cstring>

/// 构造函数
/// \param str
String::String(const char *str) : cstr(nullptr) {
    if (cstr != nullptr) {
        delete cstr;
    }
    cstr = (char *) malloc(sizeof(str) + 1);
    std::strcpy(cstr, str);
}

/// 拷贝构造函数
/// \param str
String::String(const String &str) {
    if (this == &str) {
        return;
    }
    if (cstr == str.getCstr()) {
        return;
    }
    cstr = nullptr;
    if (str.cstr != nullptr) {
        cstr = (char *) malloc(sizeof(str.cstr) + 1);
    }
    cstr = str.cstr;
}

/// 赋值构造函数
/// \param rhs
/// \return
String &String::operator=(const String &rhs) {
    if (rhs.cstr == cstr) {
        return *this;
    }
    delete cstr;
    if (rhs.cstr != nullptr) {
        cstr = (char *) malloc(sizeof(rhs.cstr) + 1);
    }
    strcpy(cstr, rhs.cstr);
    return *this;
}

String operator "" _s(const char *str, std::size_t len) {
    return String(str);
}

String &String::operator=(String &&rhs) noexcept {
    if (rhs.cstr == cstr) {
        return *this;
    }
    if (rhs.cstr == nullptr) {
        return *this;
    }
    std::strcpy(cstr, rhs.cstr);
    return *this;
}

String::String(String &&rhs) noexcept {
    if (rhs.cstr == cstr) {
        return;
    }

    delete cstr;

    cstr = (char *) malloc(sizeof(rhs.cstr) + 1);
    std::strcpy(cstr, rhs.cstr);
}

String::~String() {
    delete cstr;
}

String &operator+(String &lhs, const String &rhs) {
    using std::string;
    string l(lhs.getCstr()), r(rhs.getCstr());
    l += r;
    auto *x = new String(l.c_str());
    return *x;
}


template<typename T>
auto func_gramma_auto(T &&x) {
    return x + x;
}

#include <iostream>

void func_literal_operator() {
    using namespace std::string_literals;

    auto x = 42;
    auto y = 2.71;
    auto z = "Hello"s;
    auto xx = func_gramma_auto(z);
    auto yy = func_gramma_auto("Hello"_s);
    std::cout << "auto x= " << x << std::endl;
    std::cout << "auto y= " << y << std::endl;
    std::cout << "show String xx:" << std::string(xx) << std::endl;
    std::cout << "show String yy:" << std::string(yy.getCstr()) << std::endl;

    // String Literal
    std::cout << R"(start:literal string :\n)" << std::endl;
    std::string raw_str = R"(First line.\nSecond line.\nEnd of message.\n)";
    std::cout << R"(end:literal string :\n)" << std::endl;
    std::cout << "(end:literal string :\n)" << std::endl;
}
